home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / whrandom.py < prev    next >
Text File  |  2005-10-18  |  5KB  |  145 lines

  1. """Wichman-Hill random number generator.
  2.  
  3. Wichmann, B. A. & Hill, I. D. (1982)
  4. Algorithm AS 183:
  5. An efficient and portable pseudo-random number generator
  6. Applied Statistics 31 (1982) 188-190
  7.  
  8. see also:
  9.         Correction to Algorithm AS 183
  10.         Applied Statistics 33 (1984) 123
  11.  
  12.         McLeod, A. I. (1985)
  13.         A remark on Algorithm AS 183
  14.         Applied Statistics 34 (1985),198-200
  15.  
  16.  
  17. USE:
  18. whrandom.random()       yields double precision random numbers
  19.                         uniformly distributed between 0 and 1.
  20.  
  21. whrandom.seed(x, y, z)  must be called before whrandom.random()
  22.                         to seed the generator
  23.  
  24. There is also an interface to create multiple independent
  25. random generators, and to choose from other ranges.
  26.  
  27.  
  28.  
  29. Multi-threading note: the random number generator used here is not
  30. thread-safe; it is possible that nearly simultaneous calls in
  31. different theads return the same random value.  To avoid this, you
  32. have to use a lock around all calls.  (I didn't want to slow this
  33. down in the serial case by using a lock here.)
  34. """
  35.  
  36. import warnings
  37. warnings.warn("the whrandom module is deprecated; please use the random module",
  38.               DeprecationWarning)
  39.  
  40. # Translated by Guido van Rossum from C source provided by
  41. # Adrian Baddeley.
  42.  
  43.  
  44. class whrandom:
  45.     def __init__(self, x = 0, y = 0, z = 0):
  46.         """Initialize an instance.
  47.         Without arguments, initialize from current time.
  48.         With arguments (x, y, z), initialize from them."""
  49.         self.seed(x, y, z)
  50.  
  51.     def seed(self, x = 0, y = 0, z = 0):
  52.         """Set the seed from (x, y, z).
  53.         These must be integers in the range [0, 256)."""
  54.         if not type(x) == type(y) == type(z) == type(0):
  55.             raise TypeError, 'seeds must be integers'
  56.         if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
  57.             raise ValueError, 'seeds must be in range(0, 256)'
  58.         if 0 == x == y == z:
  59.             # Initialize from current time
  60.             import time
  61.             t = long(time.time() * 256)
  62.             t = int((t&0xffffff) ^ (t>>24))
  63.             t, x = divmod(t, 256)
  64.             t, y = divmod(t, 256)
  65.             t, z = divmod(t, 256)
  66.         # Zero is a poor seed, so substitute 1
  67.         self._seed = (x or 1, y or 1, z or 1)
  68.  
  69.     def random(self):
  70.         """Get the next random number in the range [0.0, 1.0)."""
  71.         # This part is thread-unsafe:
  72.         # BEGIN CRITICAL SECTION
  73.         x, y, z = self._seed
  74.         #
  75.         x = (171 * x) % 30269
  76.         y = (172 * y) % 30307
  77.         z = (170 * z) % 30323
  78.         #
  79.         self._seed = x, y, z
  80.         # END CRITICAL SECTION
  81.         #
  82.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
  83.  
  84.     def uniform(self, a, b):
  85.         """Get a random number in the range [a, b)."""
  86.         return a + (b-a) * self.random()
  87.  
  88.     def randint(self, a, b):
  89.         """Get a random integer in the range [a, b] including
  90.         both end points.
  91.  
  92.         (Deprecated; use randrange below.)"""
  93.         return self.randrange(a, b+1)
  94.  
  95.     def choice(self, seq):
  96.         """Choose a random element from a non-empty sequence."""
  97.         return seq[int(self.random() * len(seq))]
  98.  
  99.     def randrange(self, start, stop=None, step=1, int=int, default=None):
  100.         """Choose a random item from range(start, stop[, step]).
  101.  
  102.         This fixes the problem with randint() which includes the
  103.         endpoint; in Python this is usually not what you want.
  104.         Do not supply the 'int' and 'default' arguments."""
  105.         # This code is a bit messy to make it fast for the
  106.         # common case while still doing adequate error checking
  107.         istart = int(start)
  108.         if istart != start:
  109.             raise ValueError, "non-integer arg 1 for randrange()"
  110.         if stop is default:
  111.             if istart > 0:
  112.                 return int(self.random() * istart)
  113.             raise ValueError, "empty range for randrange()"
  114.         istop = int(stop)
  115.         if istop != stop:
  116.             raise ValueError, "non-integer stop for randrange()"
  117.         if step == 1:
  118.             if istart < istop:
  119.                 return istart + int(self.random() *
  120.                                    (istop - istart))
  121.             raise ValueError, "empty range for randrange()"
  122.         istep = int(step)
  123.         if istep != step:
  124.             raise ValueError, "non-integer step for randrange()"
  125.         if istep > 0:
  126.             n = (istop - istart + istep - 1) / istep
  127.         elif istep < 0:
  128.             n = (istop - istart + istep + 1) / istep
  129.         else:
  130.             raise ValueError, "zero step for randrange()"
  131.  
  132.         if n <= 0:
  133.             raise ValueError, "empty range for randrange()"
  134.         return istart + istep*int(self.random() * n)
  135.  
  136.  
  137. # Initialize from the current time
  138. _inst = whrandom()
  139. seed = _inst.seed
  140. random = _inst.random
  141. uniform = _inst.uniform
  142. randint = _inst.randint
  143. choice = _inst.choice
  144. randrange = _inst.randrange
  145.